package com.quanyan.orderpay.service.impl;

import com.quanyan.api.APIResponse;
import com.quanyan.common.Plugin.Page;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.utils.GsonUtils;
import com.quanyan.common.utils.StringUtil;
import com.quanyan.order.entity.Order;
import com.quanyan.order.entity.OrderExample;
import com.quanyan.order.mapper.OrderMapper;
import com.quanyan.order.mapper.UOrderMapper;
import com.quanyan.order.vo.PlatformOrderQueryPageObj;
import com.quanyan.order.vo.PlatformOrderQueryRespVo;
import com.quanyan.order.vo.PlatformOrderQueryTotalAmount;
import com.quanyan.orderpay.service.AdminOrderService;
import com.quanyan.orderpay.service.OrderProcessService;
import com.quanyan.order.entity.PlatformOrderQueryParamsVo;
import com.quanyan.orderpay.vo.request.QueryOrderParamsVo;
import com.quanyan.orderpay.vo.request.QueryRefundParamsVo;
import com.quanyan.orderpay.vo.request.UpdateRefundStatusParamsVo;
import com.quanyan.pay.entity.*;
import com.quanyan.pay.enums.PayWayEnum;
import com.quanyan.pay.enums.RefundStatusEnum;
import com.quanyan.pay.mapper.RefundRecordMapper;
import com.quanyan.pay.mapper.UPayRecordMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Zheng.Ke
 * Date 2016/8/15.
 */
@Service("adminOrderService")
public class AdminOrderServiceImpl implements AdminOrderService {
    private static Logger logger = LoggerFactory.getLogger(AdminOrderServiceImpl.class);

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RefundRecordMapper refundRecordMapper;
    @Autowired
    private OrderProcessService orderProcessService;
    @Autowired
    private UOrderMapper uOrderMapper;
    @Autowired
    private UPayRecordMapper uPayRecordMapper;

    @Override
    public APIResponse<PageObj<List<Order>>> queryOrder(QueryOrderParamsVo paramsVo) {
        OrderExample example = new OrderExample();
        OrderExample.Criteria criteria = example.createCriteria();
        Integer pageNum = paramsVo.getPageNum();
        Integer pageSize = paramsVo.getPageSize();
        String orderNo = paramsVo.getOrderNo();

        if (StringUtil.isNotBlank(orderNo)) {
            criteria.andOrderNoLike("%" + orderNo + "%");
        }

        example.setPage(new Page(pageNum*pageSize, pageSize));
        int totalCnt = orderMapper.countByExample(example);

        List<Order> orders = orderMapper.selectByExample(example);

        PageObj<List<Order>> pageObj = PageObj.create(totalCnt, pageNum, pageSize, orders);
        return APIResponse.returnSuccess(pageObj);
    }

    @Override
    public APIResponse<PageObj<List<RefundRecord>>> refundList(QueryRefundParamsVo paramsVo) {
        RefundRecordExample example = new RefundRecordExample();
        RefundRecordExample.Criteria criteria = example.createCriteria();

        Integer pageNum = paramsVo.getPageNum();
        Integer pageSize = paramsVo.getPageSize();
        String orderNo = paramsVo.getOrderNo();
        String refundStateStr = paramsVo.getRefundStateStr();

        if (StringUtil.isNotBlank(orderNo)) {
            criteria.andOrderNoLike("%" + orderNo + "%");
        }
        if (StringUtil.isNotBlank(refundStateStr)) {
            String[] refundStateListStr = refundStateStr.split(",");
            List<Byte> refundStateList = new ArrayList<Byte>();
            for (String s : refundStateListStr) {
                refundStateList.add(Byte.parseByte(s));
            }
            criteria.andRefundStateIn(refundStateList);
        }

        example.setOrderByClause("create_time desc");
        example.setPage(new Page(pageNum*pageSize, pageSize));
        int totalCnt = refundRecordMapper.countByExample(example);

        List<RefundRecord> refundRecordList = refundRecordMapper.selectByExample(example);

        PageObj<List<RefundRecord>> pageObj = PageObj.create(totalCnt, pageNum, pageSize, refundRecordList);
        return APIResponse.returnSuccess(pageObj);
    }

    @Override
    public APIResponse<RefundRecord> updateRefundStatus(UpdateRefundStatusParamsVo paramsVo) {
        Integer refundRecordId = paramsVo.getRefundRecordId();
        Byte refundState = paramsVo.getRefundState();
        RefundRecord refundRecord = refundRecordMapper.selectByPrimaryKey(refundRecordId);
        if (refundRecord == null) {
            return APIResponse.returnFail("未找到相关记录");
        }
        if (refundState != RefundStatusEnum.SUCCESS.getId()) {
            return APIResponse.returnFail("refundState非法。");
        }
        if (refundRecord.getRefundState() != RefundStatusEnum.FAIL.getId() && refundRecord.getRefundState() != RefundStatusEnum.CHANGE.getId()) {
            return APIResponse.returnFail("该退款记录不需要人工干预。");
        }

        // 退款完成处理
        RefundCompleteData refundCompleteData = new RefundCompleteData();
        refundCompleteData.setResult("SUCCESS");
        refundCompleteData.setRefundAmount(refundRecord.getRefundAmount());
        refundCompleteData.setRefundOrderNo(refundRecord.getRefundOrderNo());
        refundCompleteData.setOrderNo(refundRecord.getOrderNo());
        refundCompleteData.setPayId(refundRecord.getPayId());
        refundCompleteData.setRefundChannel(refundRecord.getRefundChannel());
        orderProcessService.refundComplateProcess(refundCompleteData);

        logger.info("人工退款成功。UpdateRefundStatusParamsVo：{}，RefundRecord：{}。", GsonUtils.toJson(paramsVo), GsonUtils.toJson(refundRecord));
        return APIResponse.returnSuccess(refundRecord);
    }

    @Override
    public APIResponse<PlatformOrderQueryPageObj<List<PlatformOrderQueryRespVo>>> platformOrderQueryList(PlatformOrderQueryParamsVo paramsVo) {
        int pageNum = paramsVo.getPageNum();
        int pageSize = paramsVo.getPageSize();

        List<PlatformOrderQueryRespVo> respVos = uOrderMapper.findPlatformOrderQueryRespVo(paramsVo);
        int totalCnt = uOrderMapper.getPlatformOrderQueryRespVoTotalCnt(paramsVo);
        //获取所有未去重的总订单金额
        BigDecimal totaNoDislOrderAmount = uOrderMapper.getNoDisTotalOrderAmount(paramsVo);
        //获取多余的总订单金额
        BigDecimal overOrderAmount = uOrderMapper.getOverOrderAmount(paramsVo);
        //获取所有未去重的支付金额（包括重复的）
        BigDecimal totalNoDisPayAmount = uOrderMapper.getNoDisPayAmount(paramsVo);
        //获取多余的总订单金额
        BigDecimal overPayAmount = uOrderMapper.getOverPayAmount(paramsVo);
        //获取所有的退款金额
        BigDecimal totalRefundActualAmount = uOrderMapper.getTotalRefundAmount(paramsVo);
//        PlatformOrderQueryTotalAmount platformOrderQueryTotalAmount =  uOrderMapper.getPlatformOrderQueryTotalAmount(paramsVo);
//        if (platformOrderQueryTotalAmount == null) {
//            platformOrderQueryTotalAmount = new PlatformOrderQueryTotalAmount();
//        }
        BigDecimal totalOrderAmount = totaNoDislOrderAmount.subtract(overOrderAmount);
        BigDecimal totalPayAmount = totalNoDisPayAmount.subtract(overPayAmount);
//        BigDecimal totalRefundActualAmount = platformOrderQueryTotalAmount.getTotalRefundActualAmount();

        // 补充赋值  (鸟蛋金额  优惠券金额等)
        respVos = assignAmountValues(respVos);

        PlatformOrderQueryPageObj<List<PlatformOrderQueryRespVo>> pageObj = new PlatformOrderQueryPageObj(totalCnt, pageNum, pageSize, respVos);
        pageObj.setTotalOrderAmount(totalOrderAmount);
        pageObj.setTotalPayAmount(totalPayAmount);
        pageObj.setTotalRefundActualAmount(totalRefundActualAmount);
        return APIResponse.returnSuccess(pageObj);
    }

    private List<PlatformOrderQueryRespVo> assignAmountValues(List<PlatformOrderQueryRespVo> respVos) {
        List<String> orderNoList = getOrderNoList(respVos);
        if (orderNoList.size() <= 0) {
            return respVos;
        }
        List<PayRecordDetail> payRecordDetailList = uPayRecordMapper.findByOrderNo(orderNoList);

        Map<String, List<PayRecordDetail>> orderNoMap = transToOrderNoMap(payRecordDetailList); // key-orderNo  value-与orderNo对应的支付详情

        for (PlatformOrderQueryRespVo vo : respVos) {
            if (PayWayEnum.PAY_WAY_WEICHAT.getPayId().equals(vo.getPayId()) || PayWayEnum.PAY_WAY_WEICHATH5.getPayId().equals(vo.getPayId()) || PayWayEnum.PAY_WAY_WEICHAT_SCAN.getPayId().equals(vo.getPayId()) || PayWayEnum.PAY_WAY_WEICHAT_APPLET.getPayId().equals(vo.getPayId())) {
                vo.setSellerAccount(vo.getSellerId());
            }
            List<PayRecordDetail> detailList = orderNoMap.get(vo.getOrderNo());
            if (detailList == null) {
                continue;
            }
            BigDecimal otherAmount = BigDecimal.ZERO;
            for (PayRecordDetail detail : detailList) {
                if (detail.getIsDelete() != null && detail.getIsDelete() == Constants.IS_DELETE_TRUE) {
                    continue;
                }
                PayWayEnum detailPayWay = PayWayEnum.getById(detail.getPayId());
                if (detailPayWay == null) {
                    continue;
                }
                switch (detailPayWay) {
                    case PAY_WAY_FOR_AGES:
                        if (detail.getPayAmount() != null) {
                            vo.setEggsAmount(detail.getPayAmount().divide(new BigDecimal(10)));
                        }
                        if (vo.getRefundState() != null) {
                            vo.setRefundEggsAmount(vo.getEggsAmount());
                        }
                        break;
                    case PAY_WAY_FOR_COUPON:
                        vo.setCouponAmount(detail.getPayAmount());
                        break;
                    case PAY_WAY_FOR_DEDUCTION:
                        otherAmount = otherAmount.add(detail.getPayAmount());
                        break;
                    case PAY_WAY_FOR_PLACE_VIP:
                        otherAmount = otherAmount.add(detail.getPayAmount());
                        break;
                    default:
                        break;
                }
            }
            vo.setOtherAmount(otherAmount);
        }
        return respVos;
    }

    private Map<String, List<PayRecordDetail>> transToOrderNoMap(List<PayRecordDetail> payRecordDetailList) {
        Map<String, List<PayRecordDetail>> orderNoMap = new HashMap<>();
        for (PayRecordDetail detail : payRecordDetailList) {
            String orderNo = detail.getOrderNo();
            if (orderNoMap.containsKey(orderNo)) {
                orderNoMap.get(orderNo).add(detail);
            } else {
                List<PayRecordDetail> detailList = new ArrayList<>();
                detailList.add(detail);
                orderNoMap.put(orderNo, detailList);
            }
        }
        return orderNoMap;
    }

    private List<String> getOrderNoList(List<PlatformOrderQueryRespVo> respVos) {
        List<String> orderNoList = new ArrayList<>();
        for (PlatformOrderQueryRespVo vo : respVos) {
            orderNoList.add(vo.getOrderNo());
        }
        return orderNoList;
    }
}
